Week Overview
Mon – Thu: Labs · Fri: Review + VM health check
Containers from first principles — and a capstone that ties the whole course together
Week 6 introduces containers — a fundamentally different approach to application deployment compared to the VMs students have worked with all course. Where a VM virtualises hardware, a container shares the host kernel and isolates only the application and its dependencies. The result: containers start in seconds, use a fraction of the memory, and pack dozens of applications onto a single server.
The week moves quickly from theory to production use. By Tuesday, students have Docker installed and running real containers with port mapping and persistent storage. Wednesday introduces docker-compose for multi-container orchestration. Thursday is the capstone: a full service stack where the Nginx server from Week 4 acts as a reverse proxy sitting in front of a Dockerised web application, resolved by the DNS zone from Week 3. Students who have kept their VMs in good health arrive at this lab with everything pre-built — they just connect the pieces.
Friday is not assessed. It is review day before the final exam — structured Q&A, a service health check on all VMs, and exam format walkthrough. Students leave with every service from Weeks 1–6 running cleanly and a clear picture of what the practical exam will ask them to do.
Week at a glance
Monday
Container Concepts & Docker Install
VMs vs containers, namespaces/cgroups, install Docker, hello-world, docker ps/images/run, interactive containers (Lab 6A)
Tuesday
Images, Port Mapping & Volumes
Docker Hub search, port binding (-p), bind mounts (-v), container logs, docker exec, networks (Lab 6B)
Wednesday
docker-compose
YAML syntax, services/networks/volumes, bring up and down, logs, scaling, restart policies (Lab 6C)
Thursday
Capstone — Nginx + Docker Stack
Deploy a containerised web app, configure Nginx proxy_pass, update DNS record, verify end-to-end (Lab 6D)
Friday
Course Review & VM Health Check
Cumulative Q&A, all services verified running, exam format walkthrough, lab catch-up
Learning Outcomes
By end of Week 6, students can…
Explain containers vs VMsDescribe how namespaces and cgroups implement container isolation without a separate kernel, and compare to hypervisor-based virtualisation
Install and operate DockerInstall docker.io, verify with docker info, pull images, run containers, and use docker ps, docker images, docker logs, and docker exec
Manage container lifecycleStart, stop, restart, and remove containers; distinguish between an image and a running container; use named containers
Map ports and bind volumesUse -p to expose container ports on the host and -v to mount host directories into containers for persistent storage
Write docker-compose filesDefine multi-container stacks in YAML with services, port mappings, volume mounts, networks, and restart policies
Configure Nginx as a reverse proxyUse proxy_pass in a location block to forward requests to a Docker container, completing the Week 4 Nginx + Week 6 Docker integration
Verify all course servicesConfirm SSH, NAT, NTP, DNS, DHCP, Nginx, and VPN are all running correctly before the final exam
Monday
Lecture + Lab 6A · 2 hrs
Container concepts, Docker install, and the first containers
0:00–0:30
Lecture
0:30–1:50
Lab 6A
1:50–2:00
Debrief
- Lecture (30 min): VMs vs containers — the architectural difference. Hypervisors virtualise hardware; containers virtualise the OS using Linux namespaces (pid, net, mnt, uts, ipc — each isolates a different resource namespace) and cgroups (control groups — limits on CPU, memory, I/O). Images vs containers — an image is a read-only template; a container is a running instance of an image, with a writable layer on top. Docker Hub as a public image registry. The Docker daemon, client, and registry architecture. Why containers start in seconds vs minutes for VMs.
- Lab 6A (80 min): Install docker.io. Verify with docker version and docker info — note the storage driver and the Docker root directory. Pull and run hello-world. Explore docker ps, docker ps -a, docker images. Run busybox interactively, use CTRL-P+CTRL-Q to detach, reattach with docker attach. Run a named container. Remove containers and images. Run doom-in-docker with port mapping as an example of a real containerised application.
- Debrief (10 min): The hello-world output explains what Docker just did — it's worth reading together. Key insight: the container ran, completed, and exited. Containers are not persistent by default — they do their job and stop. Preview Tuesday: how to make containers serve network traffic and persist data.
Instructor note: The doom-in-docker exercise is deliberately fun — it demonstrates a real GUI application running in a container and accessible through a browser, making the "containers are just processes" abstraction concrete. Let students spend a few minutes on it before moving on.
Tuesday
Lab 6B · 2 hrs
Port mapping, bind mounts, container logs, exec, and Docker networking
0:00–0:10
Recap
0:10–1:50
Lab 6B
1:50–2:00
Debrief
- Recap (10 min): Ask: "What is the difference between a Docker image and a Docker container?" — an image is the read-only template (think: an ISO file); a container is a running instance of that image (think: a running VM). You can have many containers from one image. Stopping a container doesn't delete it. Deleting a container doesn't delete the image.
- Lab 6B (100 min): Pull and run Nginx as a container with port mapping (-p 8080:80). Verify with curl and browser. Examine container logs with docker logs. Use docker exec -it to get a shell inside a running container. Run a container with a bind mount (-v) to serve local files through the Nginx container. Change the default Docker network address range via /etc/docker/daemon.json. Run a simple Ubuntu container with a custom network. Clean up: stop, remove containers, remove images.
- Debrief (10 min): The -v bind mount is the key concept — it's how containers access files that need to survive past the container's lifetime. The daemon.json network change shows containers are configurable at a deep level. Preview Wednesday: docker-compose orchestrates multiple containers in a single YAML file.
Wednesday
Lecture + Lab 6C · 2 hrs
docker-compose — multi-container orchestration and restart policies
0:00–0:10
Recap
0:10–0:40
Lecture
0:40–1:50
Lab 6C
1:50–2:00
Debrief
- Recap (10 min): Ask: "Right now, to run your bind9 container with port mapping, a bind mount, and the correct restart policy, how many flags does the docker run command need?" — many. It becomes unwieldy. docker-compose captures that entire configuration in a YAML file that can be version-controlled and re-run with a single command.
- Lecture (30 min): docker-compose YAML structure: version, services, each service has image, ports, volumes, networks, restart, environment. The docker-compose up -d (detached) and down lifecycle. docker-compose logs, docker-compose ps, docker-compose exec. Restart policies: no, always, unless-stopped, on-failure. Networks in compose — compose creates a private network for the stack automatically; services refer to each other by service name. Named volumes vs bind mounts in compose.
- Lab 6C (70 min): Write a docker-compose.yml for the ubuntu/bind9 container with bind mount to /opt/bind9/ config files, port mapping (53:53/udp), and restart: unless-stopped. Bring it up with docker-compose up -d. Verify with docker-compose ps and dig. Extend to a two-service compose file adding an Nginx container. Verify both containers run together. Add the capstone networking — an internal bridge network so the Nginx service can reach the bind9 service by name.
Thursday
Lab 6D — Capstone · 2 hrs
Nginx reverse proxy in front of a Docker web application — the course capstone
0:00–0:10
Recap
0:10–1:45
Capstone
1:45–2:00
Debrief
- Recap (10 min): Walk through what's been built in the course: DNS resolves yourname.net → Nginx on S1 → (with proxy_pass) → Docker container on S1. All three pieces exist. Today they connect.
- Capstone Lab (95 min): Run a lightweight web application in Docker (e.g., a static Nginx container serving a custom app page, or a simple Python Flask app) on a non-standard port (8080). Configure the existing Week 4 Nginx server block to proxy_pass to the container. Update the yourname.net DNS zone with an app.yourname.net A record pointing to S1. Test the full chain: browser → https://app.yourname.net → Nginx → proxy_pass → Docker container. Verify with docker logs that requests are hitting the container. Add the container to a docker-compose file for easy management with restart: unless-stopped.
- Debrief (15 min): This is the moment to reflect on the full course arc. Everything connects. The DNS from Week 3 makes the hostname work. The Nginx from Week 4 provides SSL termination and routing. The proxy_pass from the Day 4 bonus previewed this exact configuration. The container provides the application. Students who understand what they've built can describe a production web infrastructure from DNS to application — which is exactly what the final exam will test.
⭐ Capstone architecture — the full chain
- Browser requests https://app.yourname.net
- DNS (Week 3): app.yourname.net → S1's external IP (172.17.x.x)
- Nginx (Week 4): listens on 443, matches server_name app.yourname.net, applies SSL
- proxy_pass (Week 6): Nginx forwards the request to http://127.0.0.1:8080
- Docker (Week 6): container on port 8080 handles the request and returns a response
- Response travels back: container → Nginx → browser, all over HTTPS
Friday
Course Review & VM Health Check · 2 hrs · No assessment
Cumulative review, all services verified running, exam format walkthrough
0:00–0:40
Review
0:40–1:40
VM Health Check
1:40–2:00
Exam Walkthrough
- Structured review (40 min): Open Q&A covering all six content weeks. Instructor-led command reference — the most important command for each week. Students may ask about anything that was unclear.
- VM health check (60 min): Students verify all services are running and correct before the final exam. The checklist on the board: SSH key auth works on custom port, NAT routing from S2 to internet, NTP sync on all three servers, DNS zones resolve (forward and reverse), DHCP serving S2, Nginx HTTPS working, VPN (IPSec or WireGuard) tunnel up, Docker containers running with docker-compose.
- Exam format walkthrough (20 min): The final exam is a single sitting next Friday — 20 minutes written, then 100 minutes practical. The practical is scenario-based — students receive a specification and must configure services on their VMs. No internet, no notes, man pages allowed. Both portions must individually pass at 50%.
Friday VM health check — all services must be running before the final exam
| Service | Week covered | Verification command | Expected result |
| SSH — key auth on custom port | Week 1 | ssh -p [port] student@[S1-IP] | Connects without password prompt |
| NAT routing — S2 to internet | Week 1 | ping 8.8.8.8 from S2 | Replies received |
| NTP — all servers synced to S1 | Week 2 | timedatectl timesync-status on S2/S3 | ServerName = S1's IP, stratum 3 |
| DNS — forward and reverse zones | Week 3 | dig @S1 s1.yourname.net; dig -x S1-IP | Correct A and PTR records returned |
| DHCP — reservation for S2 | Week 3 | cat /var/lib/dhcp/dhcpd.leases | S2 MAC with 192.168.50.2 reservation |
| Nginx — HTTPS with 301 redirect | Week 4 | curl -v http://yourname.net | 301 redirect to https:// |
| VPN — IPSec or WireGuard tunnel | Week 5 | sudo ipsec status or sudo wg show | SA up / handshake timestamp shown |
| Docker — capstone stack running | Week 6 | docker-compose ps | All services Up |
What you need ready before Monday
All three VMs running with Week 5 services intact
Lab 6A, 6B, 6C, 6D handouts printed
Docker Hub accessible (internet from S1)
Capstone web app image decided (nginx, httpd, or simple Flask app)
Friday VM health check checklist on the board